package ejb.managerbeans;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import ejb.dto.GiftListDTO;
import ejb.dto.PacchettoDTO;
import ejb.dto.ProdottoBaseDTO;
import ejb.dto.UserDTO;
import ejb.entities.Basicproduct;
import ejb.entities.Giftlist;
import ejb.entities.Group;
import ejb.entities.Pack;
import ejb.entities.User;
import ejb.utility.ConvertDTO;

/**
 * Session Bean implementation class GiftListManagerBean
 */
@Stateless
public class GiftListManagerBean implements GiftListManagerBeanLocal {

	@PersistenceContext
	private EntityManager em;

	@Resource
	private EJBContext context;

	/**
	 * Default constructor.
	 */
	public GiftListManagerBean() {
	}

	@Override
	@RolesAllowed({ Group.USER })
	public void createGiftList(UserDTO userDTO, GiftListDTO glDTO) {
		Giftlist gl = new Giftlist(glDTO);
		User u = em.createNamedQuery(User.FINDBYID, User.class)
				.setParameter("id", userDTO.getEmail()).getSingleResult();

		// associa all'utente una nuova giftlist e alla giftlist l'utente
		// possessore
		u.addGiftlist(gl);

		try {
			em.persist(gl);
		} catch (EntityExistsException e) {
			System.out.println("L'entita esiste gia'");
		}

	}

	@Override
	@RolesAllowed({ Group.USER })
	public void addPack(PacchettoDTO packDTO, GiftListDTO glDTO) {
		// estrae giftlist e pacchetto dal db
		Pack p = (Pack) em.createNamedQuery(Pack.FIND_BYID, Pack.class)
				.setParameter("idPack", packDTO.getId()).getSingleResult();
		Giftlist gl = (Giftlist) em
				.createNamedQuery(Giftlist.FIND_BYID, Giftlist.class)
				.setParameter("id", glDTO.getId()).getSingleResult();

		// aggiunge pacchetto alla giftlist
		if (!(gl.getPacks().contains(p)))
			gl.getPacks().add(p);

		// aggiunge la giftlist al pacchetto
		if (!(p.getGiftlists().contains(gl)))
			p.getGiftlists().add(gl);
	}

	@Override
	@RolesAllowed({ Group.USER })
	public void removePack(PacchettoDTO packDTO, GiftListDTO glDTO) {
		// estraggo giftlist e pacchetto dal db
		Giftlist gl = (Giftlist) em
				.createNamedQuery(Giftlist.FIND_BYID, Giftlist.class)
				.setParameter("idGiftList", glDTO.getId()).getSingleResult();
		Pack p = (Pack) em.createNamedQuery(Pack.FIND_BYID, Pack.class)
				.setParameter("idPack", packDTO.getId()).getSingleResult();

		// estrae pacchetti contenuti in giftlist gl ed elimina il pacchetto p
		// da gl
		List<Pack> packs = gl.getPacks();

		if (packs.contains(p)) {
			packs.remove(p);
			gl.setPacks(packs);
		}

		// estrae giftlist che contengono pacchetto p ed elimina la giftlist gl
		List<Giftlist> gls = p.getGiftlists();

		if (gls.contains(p)) {
			gls.remove(gl);
			p.setGiftlists(gls);
		}
	}

	@Override
	@RolesAllowed({ Group.USER })
	public void addBasicProduct(ProdottoBaseDTO pbDTO, GiftListDTO glDTO) {
		// estraggo giftlist e prodotto base dal db
		Basicproduct bp = (Basicproduct) em
				.createNamedQuery(Basicproduct.FIND_BYID, Basicproduct.class)
				.setParameter("id", pbDTO.getId()).getSingleResult();
		Giftlist gl = (Giftlist) em
				.createNamedQuery(Giftlist.FIND_BYID, Giftlist.class)
				.setParameter("id", glDTO.getId()).getSingleResult();

		Basicproduct bpNew = em.merge(bp);
		bpNew.getGiftlists().add(gl);

	}

	@Override
	@RolesAllowed({ Group.USER })
	public void removeBasicProduct(ProdottoBaseDTO pbDTO, GiftListDTO glDTO) {
		// estraggo giftlist e prodotto base dal db
		Basicproduct bp = (Basicproduct) em
				.createNamedQuery(Basicproduct.FIND_BYID, Basicproduct.class)
				.setParameter("idBP", pbDTO.getId()).getSingleResult();
		Giftlist gl = (Giftlist) em
				.createNamedQuery(Giftlist.FIND_BYID, Giftlist.class)
				.setParameter("idGiftlist", glDTO.getId()).getSingleResult();

		// tolgo prodotto base da giftlist
		if (!(gl.getBasicproducts().contains(bp)))
			gl.getBasicproducts().remove(bp);

		// tolgo giftlist da prodotto base
		if (!(bp.getGiftlists().contains(gl)))
			bp.getGiftlists().remove(gl);
	}

	@Override
	@RolesAllowed({ Group.USER })
	public void removeGiftList(GiftListDTO glDTO) {
		// estrae dal db la giftlist
		Giftlist gl = (Giftlist) em
				.createNamedQuery(Giftlist.FIND_BYID, Giftlist.class)
				.setParameter("id", glDTO.getId()).getSingleResult();

		// toglie la giftlist dalle giftlist dell'utente
		User u = gl.getUser();
		u.removeGiftlist(gl);

		em.remove(gl);
	}

	@Override
	public List<GiftListDTO> getUserGiftListDTO(String emailUser) {

		// trova tutte le giftlist dell'utente passato come parametro
		List<Giftlist> gf = em
				.createNamedQuery(Giftlist.FINDUSERGF, Giftlist.class)
				.setParameter("idUser", emailUser).getResultList();

		List<GiftListDTO> gfDTO = new ArrayList<GiftListDTO>();

		// converte le giftlist in giftlistDTO
		for (Giftlist g : gf)
			gfDTO.add(ConvertDTO.convertToDTOGiftList(g));

		return gfDTO;
	}

	@Override
	public GiftListDTO getGfOfUser(String emailUser, String nomeGf) {
		Giftlist g = (Giftlist) em
				.createNamedQuery(Giftlist.FINDGFOFUSER, Giftlist.class)
				.setParameter("idUser", emailUser)
				.setParameter("nomeGf", nomeGf).getSingleResult();

		return ConvertDTO.convertToDTOGiftList(g);
	}

	@Override
	public List<GiftListDTO> getLoggedUserGiftListDTO() {

		User user = em.find(User.class, context.getCallerPrincipal().getName());

		// trova tutte le giftlist dell'utente passato come parametro
		List<Giftlist> gf = em
				.createNamedQuery(Giftlist.FINDUSERGF, Giftlist.class)
				.setParameter("idUser", user.getUserid()).getResultList();

		List<GiftListDTO> gfDTO = new ArrayList<GiftListDTO>();

		// converte le giftlist in giftlistDTO
		for (Giftlist g : gf)
			gfDTO.add(ConvertDTO.convertToDTOGiftList(g));

		return gfDTO;
	}
}